package com.odata.springboot.starter.odata.odata.processor;

import com.odata.springboot.starter.odata.odata.sql.sqlBuild.OdataSqlInfo;
import com.odata.springboot.starter.odata.odata.sql.sqlBuild.OdataSqlInformation;
import com.odata.springboot.starter.odata.utils.OdataJdbcUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.olingo.commons.api.data.ContextURL;
import org.apache.olingo.commons.api.data.Entity;
import org.apache.olingo.commons.api.data.Property;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
import org.apache.olingo.commons.api.edm.EdmProperty;
import org.apache.olingo.commons.api.format.ContentType;
import org.apache.olingo.commons.api.http.HttpHeader;
import org.apache.olingo.commons.api.http.HttpStatusCode;
import org.apache.olingo.server.api.*;
import org.apache.olingo.server.api.processor.PrimitiveProcessor;
import org.apache.olingo.server.api.serializer.ODataSerializer;
import org.apache.olingo.server.api.serializer.PrimitiveSerializerOptions;
import org.apache.olingo.server.api.serializer.SerializerResult;
import org.apache.olingo.server.api.uri.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.InputStream;
import java.util.Collections;
import java.util.List;
import java.util.Locale;

/**
 * 对单个进行操作
 * @author chenYX
 * @date 2021/6/22 16:34
 * @description
 */
@Component
@Slf4j
public class SimplePrimitiveProcessor implements PrimitiveProcessor {

    private OData odata;
    private ServiceMetadata serviceMetadata;

    @Autowired
    private OdataJdbcUtils odataJdbcUtils;



    @Override
    public void readPrimitive(ODataRequest oDataRequest, ODataResponse oDataResponse, UriInfo uriInfo, ContentType contentType) throws ODataApplicationException, ODataLibraryException {
        // 1. Retrieve info from URI
        // 1.1. retrieve the info about the requested entity set
        List<UriResource> resourceParts = uriInfo.getUriResourceParts();
        // Note: only in our example we can rely that the first segment is the EntitySet
        UriResourceEntitySet uriEntityset = (UriResourceEntitySet) resourceParts.get(0);
        EdmEntitySet edmEntitySet = uriEntityset.getEntitySet();
        // the key for the entity
        List<UriParameter> keyPredicates = uriEntityset.getKeyPredicates();

        // 1.2. retrieve the requested (Edm) property
        // the last segment is the Property
        UriResourceProperty uriProperty = (UriResourceProperty) resourceParts.get(resourceParts.size() -1);
        EdmProperty edmProperty = uriProperty.getProperty();
        String edmPropertyName = edmProperty.getName();
        // in our example, we know we have only primitive types in our model
        EdmPrimitiveType edmPropertyType = (EdmPrimitiveType) edmProperty.getType();

        String className = uriEntityset.getEntityType().getFullQualifiedName().getFullQualifiedNameAsString();
        Entity entity = new Entity();
        try {
            Class<?> aClass = Class.forName(className);
            OdataSqlInformation.SqlInformationBuild sqlInformationBuild = new OdataSqlInformation.SqlInformationBuild();
            sqlInformationBuild.createFilterString();
            sqlInformationBuild.buildPrimaryKeyAndClassForSelectFields(keyPredicates.get(0).getText(),aClass, Collections.singletonList(edmProperty.getName()));
            OdataSqlInfo odataSqlInfo = sqlInformationBuild.buildSqlInfo();
            entity = odataJdbcUtils.executeSelectSqlAnd2Entity(odataSqlInfo);
        } catch (Exception e) {
            log.error("sql读取单个数据失败{}",e.getMessage(),e);
        }

        if (entity == null) { // Bad request
            throw new ODataApplicationException("Entity not found",
                    HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ENGLISH);
        }
        Property property = entity.getProperty(edmPropertyName);
        if (property == null) {
            throw new ODataApplicationException("Property not found",
                    HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ENGLISH);
        }

        Object value = property.getValue();
        if (value != null) {
            ODataSerializer serializer = odata.createSerializer(contentType);
            ContextURL contextUrl = ContextURL.with().entitySet(edmEntitySet).navOrPropertyPath(edmPropertyName).build();
            PrimitiveSerializerOptions options = PrimitiveSerializerOptions.with().contextURL(contextUrl).build();
            SerializerResult serializerResult = serializer.primitive(serviceMetadata, edmPropertyType, property, options);
            InputStream propertyStream = serializerResult.getContent();
            oDataResponse.setContent(propertyStream);
            oDataResponse.setStatusCode(HttpStatusCode.OK.getStatusCode());
            oDataResponse.setHeader(HttpHeader.CONTENT_TYPE, contentType.toContentTypeString());
        }else{
            oDataResponse.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
        }
    }

    @Override
    public void updatePrimitive(ODataRequest oDataRequest, ODataResponse oDataResponse, UriInfo uriInfo, ContentType contentType, ContentType contentType1) throws ODataApplicationException, ODataLibraryException {

    }

    @Override
    public void deletePrimitive(ODataRequest oDataRequest, ODataResponse oDataResponse, UriInfo uriInfo){

    }

    @Override
    public void init(OData oData, ServiceMetadata serviceMetadata) {
        this.odata = oData;
        this.serviceMetadata = serviceMetadata;
    }
}
